import { deepClone, exportDefault, titleCase } from '@/utils'
import ruleTrigger from '@/components/generator/ruleTrigger'

const units = {
  KB: '1024',
  MB: '1024 / 1024',
  GB: '1024 / 1024 / 1024'
}

let confGlobal
const inheritAttrs = {
  file: '',
  dialog: 'inheritAttrs: false,'
}

/**
 * 组装js
 * @param formConfig 表单配置项
 * @param type 生成类型，文件或者弹窗
 * @returns {string}
 */
export function makeUpJs (formConfig, type) {
  confGlobal = formConfig = deepClone(formConfig)
  const dataList = []
  const ruleList = []
  const optionsList = []
  const propsList = []
  const methodList = mixinMethod(type)
  const uploadVarList = []
  const created = []

  formConfig.fields.forEach(el => {
    buildAttributes(el, dataList, ruleList, optionsList, methodList, propsList, uploadVarList, created)
  })

  const script = buildExport(
    formConfig,
    type,
    dataList.join('\n'),
    ruleList.join('\n'),
    optionsList.join('\n'),
    uploadVarList.join('\n'),
    propsList.join('\n'),
    methodList.join('\n'),
    created.join('\n')
  )
  confGlobal = null
  return script
}

function mixinMethod (type) {
  const list = []
  const mixins = {
    file: confGlobal.formBtns ? {
      submitForm: `submitForm(){
        this.$refs['${confGlobal.formRef}'].validate(valid => {
          if(!valid) return
          // TODO 提交表单
        })
      },`,
      resetForm: `resetForm(){
        this.$refs['${confGlobal.formRef}'].resetFields()
      },`
    } : null,
    dialog: {
      onOpen: 'onOpen() {},',
      onClose: `onClose() {
        this.$refs['${confGlobal.formBtns}'].resetFields()
      },`,
      close: 'close(){this.$emit(\'update:visible\', false)},',
      handelConfirm: `handelConfirm() {
        this.$refs['${confGlobal.formRef}'].validate(valid => {
          if(!valid) return
          this.close()
        })
      },`
    }
  }
  const methods = mixins[type]
  if (methods) {
    Object.keys(methods).forEach(key => {
      list.push(methods[key])
    })
  }
  return list
}

// 构建组件属性
function buildAttributes (scheme, dataList, ruleList, optionsList, methodList, propsList, uploadVarList, created) {
  const config = scheme.config
  const slot = scheme.slot
  buildData(scheme, dataList)
  buildRules(scheme, ruleList)

  // 特殊处理options属性
  if (scheme.options || (slot && slot.options && slot.options.length)) {
    buildOptions(scheme, optionsList)
    if (config.dataType === 'dynamic') {
      const model = `${scheme.vModel}Options`
      const options = titleCase(model)
      const methodName = `get${options}`
      buildOptionsMethod(methodName, model, methodList, scheme)
      callInCreated(methodName, created)
    }
  }

  // 处理props
  if (scheme.props && scheme.props.props) {
    buildProps(scheme, propsList)
  }

  // 处理el-upload的action
  if (scheme.action && config.tag === 'el-upload') {
    uploadVarList.push(
      `${scheme.vModel}Action: '${scheme.action}',
      ${scheme.vModel}fileList: [],`
    )
    methodList.push(buildBeforeUpload(scheme))
    // 非自动上传时，生成手动上传的函数
    if (!scheme['auto-upload']) {
      methodList.push(buildSubmitUpload(scheme))
    }
  }

  // 构建子级组件属性
  if (config.children) {
    config.children.forEach(item => {
      buildAttributes(item, dataList, ruleList, optionsList, methodList, propsList, uploadVarList, created)
    })
  }
}

// 构建data
function buildData (scheme, dataList) {
  const config = scheme.config
  if (scheme.vModel === undefined) return
  const defaultValue = JSON.stringify(config.defaultValue)
  dataList.push(`${scheme.vModel}: ${defaultValue},`)
}

// 构建校验规则
function buildRules (scheme, ruleList) {
  const config = scheme.config
  if (scheme.vModel === undefined) return
  const rules = []
  if (ruleTrigger[config.tag]) {
    if (config.required) {
      const type = Array.isArray(config.defaultValue) ? 'type: \'array\',' : ''
      let message = Array.isArray(config.defaultValue) ? `请至少选择一个${config.label}` : scheme.placeholder
      if (message === undefined) message = `${config.label}不能为空`
      rules.push(`{ required: true, ${type} message : '${message}', trigger: '${ruleTrigger[config.tag]}' }`)
    }
    if (config.regList && Array.isArray(config.regList)) {
      config.regList.forEach(item => {
        if (item.pattern) {
          rules.push(
            // eslint-disable-next-line no-eval
            `{ pattern: ${eval(item.pattern)}, message: '${item.message}', trigger: '${ruleTrigger[config.tag]}' }`
          )
        }
      })
    }
    ruleList.push(`${scheme.vModel}: [${rules.join(',')}],`)
  }
}

// 构建options
function buildOptions (scheme, optionsList) {
  if (scheme.vModel === undefined) return
  // el-cascader直接有options属性，其他组件都是定义在slot中，所以有两处判断
  let { options } = scheme
  if (!options) options = scheme.slot.options
  if (scheme.config.dataType === 'dynamic') { options = [] }
  const str = `${scheme.vModel}Options: ${JSON.stringify(options)},`
  optionsList.push(str)
}

// 构建method
function buildOptionsMethod (methodName, model, methodList, scheme) {
  const config = scheme.config
  const str = `${methodName}(){
    this.$axios({method: '${config.method}', url: '${config.url}'}).then(response => {
      const { data } = response
      this.${model} = data.${config.dataPath}
    })
  },`
  methodList.push(str)
}

// created调用函数
function callInCreated (methodName, created) {
  created.push(`this.${methodName}()`)
}

function buildProps (scheme, propsList) {
  const str = `${scheme.vModel}Props: ${JSON.stringify(scheme.props.props)},`
  propsList.push(str)
}

// el-upload的BeforeUpload
function buildBeforeUpload (scheme) {
  const config = scheme.config
  const unitNum = units[config.sizeUnit]
  let rightSizeCode = ''
  let acceptCode = ''
  const returnList = []
  if (config.fileSize) {
    rightSizeCode = `let isRightSize = file.size / ${unitNum} < ${config.fileSize}
    if(!isRightSize){
      this.$message.error('文件大小超过 ${config.fileSize}${config.sizeUnit}')
    }`
    returnList.push('isRightSize')
  }
  if (scheme.accept) {
    acceptCode = `let isAccept = new RegExp('${scheme.accept}').test(file.type)
    if(!isAccept){
      this.$message.error('应该选择${scheme.accept}类型的文件')
    }`
    returnList.push('isAccept')
  }
  const str = `${scheme.vModel}BeforeUpload(file) {
    ${rightSizeCode}
    ${acceptCode}
    return ${returnList.join('&&')}
  },`
  return returnList.length ? str : ''
}

// el-upload的submit
function buildSubmitUpload (scheme) {
  return `submitUpload() {
    this.$refs['${scheme.vModel}'].submit()
  },`
}

// js整体拼接
function buildExport (conf, type, data, rules, selectOptions, uploadVar, props, methods, created) {
  return `${exportDefault}{
    ${inheritAttrs[type]}
    components: {},
    props: [],
    data () {
      return {
        ${conf.formModel}: {
          ${data}
        },
        ${conf.formRules}: {
          ${rules}
        },
        ${uploadVar}
        ${selectOptions}
        ${props}
      }
    },
    computed: {},
    watch: {},
    created () {
      ${created}
    },
    mounted () {},
    methods: {
      ${methods}
    }
  }`
}
